package org.mtree.context.wrapper;

import java.util.Collection;
import java.util.HashSet;

import org.mtree.context.Context;
import org.mtree.context.ContextHelper;

/**
 * 复合上下文，体现上下文的继承关系
 * 
 * @author rushman
 * @date 2017-11-04
 */
public class ComplexContextWrapper implements Context {

    private final Context parent;
    private final Context current;

    public ComplexContextWrapper(Context context) {
        super();
        this.parent = ContextHelper.getDefaultContext();
        this.current = context;
    }

    public ComplexContextWrapper(Context parentContext, Context context) {
        super();
        this.parent = parentContext == null ? ContextHelper.getDefaultContext() : parentContext;
        this.current = context;
    }

    public ComplexContextWrapper push(Context context) {
        return new ComplexContextWrapper(this, context);
    }

    /**
     * 导出当前上下文属性到上级上下文
     * 
     * @param name 属性名
     */
    public void export(String name) {
        Object value = current.get(name);
        if (value != null) {
            parent.set(name, value);
        }
    }

    /**
     * 设置上下文属性并导出之上级上下文
     * 
     * @param name 属性名
     * @param value 属性值
     */
    public void export(String name, Object value) {
        this.set(name, value);
        export(name);
    }

    @Override
    public Object get(String name) {
        Object value = current.get(name);
        if (value == null) {
            return parent.get(name);
        }
        return value;
    }

    @Override
    public Object set(String name, Object value) {
        return current.set(name, value);
    }

    @Override
    public Object remove(String name) {
        return current.remove(name);
    }

    @Override
    public boolean has(String name) {
        return current.has(name) || parent.has(name);
    }

    @Override
    public Collection<String> nameSet() {
        Collection<String> nameSet = new HashSet<String>();
        if (parent != null) {
            nameSet.addAll(parent.nameSet());
        }
        nameSet.addAll(current.nameSet());
        return nameSet;
    }

}
